const PENDING = 'pending'  // 等待
const FULFILLED = 'fulfilled'   // fulfilled
const REJECTED = 'rejected'   // rejected

class MyPromise {
  constructor(executor) {
    // Promise 状态
    this.status = PENDING
    // fulfilled后的值
    this.value = undefined
    // rejected后的原因
    this.reason = undefined

    // resolve 时待执行的队列
    this._onResolvedList = []
    // rejected 时待执行的队列
    this._onRejectedList = []

    this._onResolve = (value) => {
      // 如果状态不为 pending，将状态更改为 fulfilled
      if (this.status !== PENDING) return
      this.status = FULFILLED
      // 保存 fulfilled 的值
      this.value = value
      this._onResolvedList.forEach(fn => fn(value))
    }

    this._onReject = (reason) => {
      // 如果状态不为 pending，将状态更改为 rejected
      if (this.status !== PENDING) return
      this.status = REJECTED
      // 保存 rejected 的原因
      this.reason = reason
      this._onRejectedList.forEach(fn => fn(this.reason))

    }

    // promise 解析, 根据 then 返回数据类型不同封装不同的promise返回，以便实现then的链式调用及Promise的thenable特性 
    this._resolvePromise = (data, resolve, reject) => {
      // then 返回的是 promise
      if (data instanceof MyPromise) {
        data.then(resolve, reject)

        // then 返回的是普通数据
      } else {
        resolve(data)
      }
    }

    // 初始化时调用执行器，传入resolve、reject方法
    try {
      executor(this._onResolve, this._onReject)
    } catch (error) {
      this._onReject(error)
    }
  }

  /*
  then 方法返回一个 promise
  传入 then 的参数不是函数，直接将目前 promise 中的数据 resolve 或 reject 传入新的 promise 并返回
  传入的参数是函数，则将目前 promise 中的数据作为参数传入函数中执行，并将返回值解析(_resolvePromise)为 promise
  */
  then(resolveCallback, rejectCallback) {
    let promise

    // 状态为 pending，
    if (this.status === PENDING) {
      promise = new MyPromise((resolve, reject) => {
        this._onResolvedList.push(() => {
          if (!(resolveCallback instanceof Function)) {
            // 如果传入的参数不是函数，直接 resolve 当前 promise 的值
            resolve(this.value)
          } else {
            // 如果传入的参数是函数，直接执行该函数并将返回值解析为 promise
            let data = resolveCallback(this.value)
            this._resolvePromise(data, resolve, reject)
          }
        })

        this._onRejectedList.push(() => {
          if (!(rejectCallback instanceof Function)) {
            // 如果传入的参数不是函数，直接 resolve 当前 promise 的值
            reject(this.reason)
          } else {
            // 如果传入的参数是函数，直接执行该函数并将返回值解析为 promise
            let data = rejectCallback(this.reason)
            this._resolvePromise(data, resolve, reject)
          }
        })
      })

    } else if (this.status === FULFILLED) {
      // 如果状态为 fulfilled，调用 fulfilled 的回调
      promise = new MyPromise((resolve, reject) => {
        if (!(resolveCallback instanceof Function)) {
          // 如果传入的参数不是函数，直接 resolve 当前 promise 的值
          resolve(this.value)
        } else {
          // 如果传入的参数是函数，直接执行该函数并将返回值解析为 promise
          let data = resolveCallback(this.value)
          this._resolvePromise(data, resolve, reject)
        }
      })

    } else {
      // 如果状态为 rejected，与 fulfilled 类似
      promise = new MyPromise((resolve, reject) => {
        if (!(rejectCallback instanceof Function)) {
          // 如果传入的参数不是函数，直接 reject 当前 promise 的值
          reject(this.reason)
        } else {
          // 如果传入的参数是函数，直接执行该函数并将返回值解析为 promise
          let data = rejectCallback(this.reason)
          this._resolvePromise(data, resolve, reject)
        }
      })
    }

    return promise
  }

  catch(callback) {
    this.then(null, callback)
  }

  static all(arr) {
    if (!(arr[Symbol.iterator])) {
      // 如果传入的值不支持 iterator 接口，直接抛出错误
      throw new TypeError('Parameters must support iterator interfaces')
    } else {
      return new MyPromise((resolve, reject) => {
        let result = []
        // 当前 result 中有多少结果
        let i = 0
        if (arr.length == 0) resolve(arr)
        arr.forEach((item, index) => {
          if (item instanceof MyPromise) {
            // 当前元素是 promise，将其结果传入数组中
            item.then(res => {
              result[index] = res
              i++
              // 所有结果都已获取到
              if (i == arr.length) resolve(result)
            }, reject)
          } else {
            // 当前元素不是 promise，直接推入结果数组汇总
            result[index] = item
            i++
            // 所有结果都已获取到
            if (i == arr.length) resolve(result)
          }
        })
      })
    }
  }

  static race(arr) {
    if (!(arr[Symbol.iterator])) {
      // 如果传入的值不支持 iterator 接口，直接抛出错误
      throw new TypeError('Parameters must support iterator interfaces')
    } else {
      return new MyPromise((resolve, reject) => {
        // 传入的参数是空的，不执行操作
        if (arr.length == 0) return
        arr.forEach(item => {
          if (item instanceof MyPromise) {
            // 当前元素是 promise
            item.then(resolve, reject)
          } else {
            // 当前元素不是 promise
            resolve(item)
          }
        })
      })
    }
  }

  static any(arr) {
    if (!(arr[Symbol.iterator])) {
      // 如果传入的值不支持 iterator 接口，直接抛出错误
      throw new TypeError('Parameters must support iterator interfaces')
    } else {
      return new MyPromise((resolve, reject) => {
        // 传入的参数是空的，不执行操作
        if (arr.length == 0) return
        arr.forEach(item => {
          if (item instanceof MyPromise) {
            // 当前元素是 promise，因为始终返回一个 resolve 的值，所以不执行 reject 操作
            item.then(resolve)
          } else {
            // 当前元素不是 promise
            resolve(item)
          }
        })
      })
    }
  }

  static resolve(val) {
    // 如果参数是 promise，直接返回
    if (val instanceof MyPromise) return val
    return new MyPromise((resolve, reject) => {
      resolve(val)
    })
  }

  static reject(val) {
    // 如果参数是 promise，直接返回
    if (val instanceof MyPromise) return val
    return new MyPromise((resolve, reject) => {
      reject(val)
    })
  }
}

module.exports = MyPromise